package org.dromara.common.vcp.utils;

/**
 * @author cbx
 * @date 2020/7/3
 **/
public class ByteFormat {
    //字符集转换
    public static String bytesToHexString(byte[] bArray) {
        StringBuilder sb = new StringBuilder(bArray.length);
        String sTemp;
        for (byte b : bArray) {
            sTemp = Integer.toHexString(0xFF & b);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }
    /**
     * 将byte数组转换为十六进制文本
     */
    public static String toHex(byte[] buf) {
        if (buf == null || buf.length == 0) {
            return "";
        }
        StringBuilder out = new StringBuilder();
        for (byte b : buf) {
            out.append(HEX[(b >> 4) & 0x0f]).append(HEX[b & 0x0f]);
        }
        return out.toString();
    }

    /**
     * 将十六进制文本转换为byte数组
     */
    public static byte[] hexToBytes(String str) {
        if (str == null) {
            return null;
        }
        char[] hex = str.toCharArray();
        int length = hex.length / 2;
        byte[] raw = new byte[length];
        for (int i = 0; i < length; i++) {
            int high = Character.digit(hex[i * 2], 16);
            int low = Character.digit(hex[i * 2 + 1], 16);
            int value = (high << 4) | low;
            if (value > 127)
                value -= 256;
            raw[i] = (byte) value;
        }
        return raw;
    }

    /**
     * 将byte数组转换为格式化的十六进制文本
     */
    public static String dumpHex(byte[] buf) {
        if (buf == null) {
            return "";
        }
        return dumpHex(buf, 0, buf.length);
    }

    /**
     * 将byte数组转换为格式化的十六进制文本
     */
    public static String dumpHex(byte[] buf, int offset, int numBytes) {
        if (buf == null || buf.length == 0) {
            return "";
        }

        if (offset >= buf.length) {
            offset = buf.length - 1;
        }

        if (numBytes > buf.length - offset) {
            numBytes = buf.length - offset;
        }

        StringBuilder out = new StringBuilder();

        int			rows, residue, i, j;
        byte[]		save_buf= new byte[ ROW_BYTES+2 ];
        char[]		hex_buf = new char[ 4 ];
        char[]		idx_buf = new char[ 8 ];

        rows = numBytes >> 4;
        residue = numBytes & 0x0000000F;
        for ( i = 0 ; i < rows ; i++ ) {
            int hexVal = (i * ROW_BYTES);
            idx_buf[0] = HEX[ ((hexVal >> 12) & 15) ];
            idx_buf[1] = HEX[ ((hexVal >> 8) & 15) ];
            idx_buf[2] = HEX[ ((hexVal >> 4) & 15) ];
            idx_buf[3] = HEX[ (hexVal & 15) ];

            String idxStr = new String( idx_buf, 0, 4 );
            out.append( idxStr + ": " );

            for ( j = 0 ; j < ROW_BYTES ; j++ ) {
                save_buf[j] = buf[ offset + (i * ROW_BYTES) + j ];

                hex_buf[0] = HEX[ (save_buf[j] >> 4) & 0x0F ];
                hex_buf[1] = HEX[ save_buf[j] & 0x0F ];

                out.append( hex_buf[0] );
                out.append( hex_buf[1] );
                out.append( ' ' );

                if ( j == ROW_QTR1 || j == ROW_HALF || j == ROW_QTR2 )
                    out.append( ' ' );

                if ( save_buf[j] < 0x20 || save_buf[j] > 0x7E )
                    save_buf[j] = (byte) '.';
            }

            String saveStr = new String( save_buf, 0, j );
            out.append(" ; ").append(saveStr).append("\n");
        }

        if ( residue > 0 ) {
            int hexVal = (i * ROW_BYTES);
            idx_buf[0] = HEX[ ((hexVal >> 12) & 15) ];
            idx_buf[1] = HEX[ ((hexVal >> 8) & 15) ];
            idx_buf[2] = HEX[ ((hexVal >> 4) & 15) ];
            idx_buf[3] = HEX[ (hexVal & 15) ];

            String idxStr = new String( idx_buf, 0, 4 );
            out.append(idxStr).append(": ");

            for ( j = 0 ; j < residue ; j++ ) {
                save_buf[j] = buf[ offset + (i * ROW_BYTES) + j ];

                hex_buf[0] = HEX[ (save_buf[j] >> 4) & 0x0F ];
                hex_buf[1] = HEX[ save_buf[j] & 0x0F ];

                out.append( (char)hex_buf[0] );
                out.append( (char)hex_buf[1] );
                out.append( ' ' );

                if ( j == ROW_QTR1 || j == ROW_HALF || j == ROW_QTR2 )
                    out.append( ' ' );

                if ( save_buf[j] < 0x20 || save_buf[j] > 0x7E )
                    save_buf[j] = (byte) '.';
            }

            for ( /*j INHERITED*/ ; j < ROW_BYTES ; j++ ) {
                save_buf[j] = (byte) ' ';
                out.append( "   " );
                if ( j == ROW_QTR1 || j == ROW_HALF || j == ROW_QTR2 )
                    out.append( " " );
            }

            String saveStr = new String( save_buf, 0, j );
            out.append(" ; ").append(saveStr).append("\n");
        }

        return out.toString();
    }

    private final static char[] HEX = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'D', 'E', 'F' };

    private static final int ROW_BYTES = 16;
    private static final int ROW_QTR1 = 3;
    private static final int ROW_HALF = 7;
    private static final int ROW_QTR2 = 11;

}
